﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.ReactiveUI;
using Avalonia.Skia;
using SkiaSharp;
using TCP232.PublicMethod;

namespace TCP232
{
    internal class Program
    {
        // Initialization code. Don't use any Avalonia, third-party APIs or any
        // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
        // yet and stuff might break.
        [STAThread]
        public static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
            {
                Exception ex = e.ExceptionObject as Exception;
                MessageTip.ShowError("在工作线程发生未捕获的异常：\n" + ex?.ToString());
            };
            ////全局捕获Task中未观察到的异常
            //TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs e) =>
            //{
            //    MessageTip.Show($"{e.Exception.Message}\n{e.Exception.InnerException}");
            //};


            //DispatcherUnhandledException
            try
            { 
                BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
            }
            catch (Exception ex)
            {
                WriteErrorLog(ex.ToString());
            }
        }

        // Avalonia configuration, don't remove; also used by visual designer.
        public static AppBuilder BuildAvaloniaApp()
            => AppBuilder.Configure<App>()
                .UsePlatformDetect()
                .LogToTrace()
                .UseReactiveUI();

        static void WriteErrorLog(string message)
        {
            try
            {
                //string folder = $"{Const.ErrorLog}/{DateTime.Now:yyyy-MM}";
                DateTime dateTime = DateTime.Now;
                string folder = "ErrorLog";
                //if (!Directory.Exists(folder))//判断文件夹是否存在
                //{
                //    Directory.CreateDirectory(folder);
                //}
                using StreamWriter file = new StreamWriter($"{folder}/{dateTime:yyyy-MM-dd}.txt", true);
                file.WriteLine($"[{dateTime:yyyy-MM-dd HH:mm:ss.fff}]{message}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }
    }

    public class CustomFontManagerImpl : IFontManagerImpl
    {
        private readonly Typeface[] _customTypefaces;
        private readonly string _defaultFamilyName;

        //Load font resources in the project, you can load multiple font resources
        private readonly Typeface _defaultTypeface =
            new Typeface("avares://TCP232/Assets/Fonts/OPPOSans-M.ttf#OPPOSans M");

        public CustomFontManagerImpl()
        {
            _customTypefaces = new[] { _defaultTypeface };
            _defaultFamilyName = _defaultTypeface.FontFamily.FamilyNames.PrimaryFamilyName;
        }

        public string GetDefaultFontFamilyName()
        {
            return _defaultFamilyName;
        }

        public IEnumerable<string> GetInstalledFontFamilyNames(bool checkForUpdates = false)
        {
            return _customTypefaces.Select(x => x.FontFamily.Name);
        }

        private readonly string[] _bcp47 =
        {
            CultureInfo.CurrentCulture.ThreeLetterISOLanguageName, CultureInfo.CurrentCulture.TwoLetterISOLanguageName
        };

        public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fontWeight, FontFamily fontFamily,
            CultureInfo culture, out Typeface typeface)
        {
            foreach (var customTypeface in _customTypefaces)
            {
                if (customTypeface.GlyphTypeface.GetGlyph((uint)codepoint) == 0)
                {
                    continue;
                }

                typeface = new Typeface(customTypeface.FontFamily.Name, fontStyle, fontWeight);

                return true;
            }

            var fallback = SKFontManager.Default.MatchCharacter(fontFamily?.Name, (SKFontStyleWeight)fontWeight,
                SKFontStyleWidth.Normal, (SKFontStyleSlant)fontStyle, _bcp47, codepoint);

            typeface = new Typeface(fallback?.FamilyName ?? _defaultFamilyName, fontStyle, fontWeight);

            return true;
        }

        private static string GetPlatformFontFamily()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return "Microsoft YaHei";
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                return "Menlo"; //换成OSX下的中文字体
            }
            else
            {
                return "Noto Sans CJK SC";
            }
        }

        public static SKTypeface GetTypeface()
        {
            var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
            SKTypeface result = SKTypeface.FromStream(assets.Open(new Uri("avares://TCP232/Assets/Fonts/OPPOSans-M.ttf")));
            return result;
        }

        public IGlyphTypefaceImpl CreateGlyphTypeface(Typeface typeface)
        {
            return new GlyphTypefaceImpl(GetTypeface());
        }
    }
}